package com.cloudlead.utils.persistence.codegen.serializer;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.mysema.codegen.CodeWriter;
import com.mysema.query.codegen.EntityType;
import com.mysema.query.codegen.Serializer;
import com.mysema.query.codegen.SerializerConfig;

public class SimpleDaoIfcSerializer implements Serializer {

	private final String javadocSuffix;

	private boolean printSupertype = true;

	/**
	 * Create a new BeanSerializer
	 */
	public SimpleDaoIfcSerializer() {
		this(" is a Querydsl repository interface type");
	}

	/**
	 * Create a new BeanSerializer with the given javadoc suffix
	 * 
	 * @param javadocSuffix
	 */
	public SimpleDaoIfcSerializer(String javadocSuffix) {
		this.javadocSuffix = javadocSuffix;
	}

	public void serialize(EntityType model, SerializerConfig serializerConfig,
			CodeWriter writer) throws IOException {
		String simpleName = model.getSimpleName();

		// package
		if (!model.getPackageName().isEmpty()) {
			writer.packageDecl(model.getPackageName());
		}

		// imports
		Set<String> importedClasses = getAnnotationTypes(model);
		if (model.hasLists()) {
			importedClasses.add(List.class.getName());
		}
		if (model.hasCollections()) {
			importedClasses.add(Collection.class.getName());
		}
		if (model.hasSets()) {
			importedClasses.add(Set.class.getName());
		}
		if (model.hasMaps()) {
			importedClasses.add(Map.class.getName());
		}
		writer.importClasses(model.getSuperType().getType().getFullName());
		writer.importClasses(model.getSuperType().getType().getParameters().get(0).getFullName());
		writer.importClasses(importedClasses.toArray(new String[importedClasses
				.size()]));

		// javadoc
		writer.javadoc(simpleName + javadocSuffix);

		// header
		for (Annotation annotation : model.getAnnotations()) {
			writer.annotation(annotation);
		}

		if (printSupertype && model.getSuperType() != null) {
			writer.beginInterface(model, model.getSuperType().getType());
		} else {
			writer.beginInterface(model);
		}

		bodyStart(model, writer);

		bodyEnd(model, writer);

		writer.end();
	}

	protected void bodyStart(EntityType model, CodeWriter writer)
			throws IOException {

	}

	protected void bodyEnd(EntityType model, CodeWriter writer)
			throws IOException {
		// template method
	}

	private Set<String> getAnnotationTypes(EntityType model) {
		Set<String> imports = new HashSet<String>();
		for (Annotation annotation : model.getAnnotations()) {
			imports.add(annotation.annotationType().getName());
		}
		return imports;
	}

	public void setPrintSupertype(boolean printSupertype) {
		this.printSupertype = printSupertype;
	}

}
